/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-通用能力封装层-公共组件
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.utility.extend;

import com.taipingframework.utility.exception.UtilityException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.codec.binary.Hex;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串处理帮助类
 */
public class StringHelper {

    /**
     * 删除字符串source开头的指定字符prefix
     */
    public static String trimStart(String source, String prefix) {
        return source.replaceAll("^" + prefix, "");
    }

    /**
     * 删除字符串source结尾的指定字符suffix
     */
    public static String trimEnd(String source, String suffix) {
        return source.replaceAll(suffix + "$", "");
    }

    /**
     * 删除字符串source首尾的指定字符chr
     */
    public static String trim(String source, String chr) {
        return source.replaceAll("(^" + chr + ")|(" + chr + "$)", "");
    }

    /**
     * 字符串source是否以prefix开头
     */
    public static boolean startWith(String source, String prefix) {
        Pattern compile = Pattern.compile("^" + prefix, Pattern.CASE_INSENSITIVE);
        return compile.matcher(source).find();
    }

    /**
     * 字符串source是否以prefix结尾
     */
    public static boolean endWith(String source, String suffix) {
        Pattern compile = Pattern.compile(suffix + "$", Pattern.CASE_INSENSITIVE);
        return compile.matcher(source).find();
    }

    /**
     * Decode the value using Base64.
     *
     * @param base64Value the Base64 String to decode
     * @return the Base64 decoded value
     */
    public static String base64Decode(String base64Value) throws UtilityException {
        try {
            byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
            return new String(decodedCookieBytes);
        } catch (Exception ex) {
            throw new UtilityException(ex);
        }
    }

    /**
     * Encode the value using Base64.
     *
     * @param value the String to Base64 encode
     * @return the Base64 encoded value
     */
    public static String base64Encode(String value) {
        byte[] encodedCookieBytes = Base64.getEncoder().encode(value.getBytes());
        return new String(encodedCookieBytes);
    }

    /**
     * 获取到形如字符串“pattern{0}_{1}_{2}”中的{0}和{1}以及{2}，以集合的形式将结果返回：[0, 1, 2]
     */
    public static List<String> matchQuoteContent(String pattern) {
        Pattern regex = Pattern.compile("\\{(.*?)}", Pattern.DOTALL);
        Matcher matcher = regex.matcher(pattern);
        List<String> result = new ArrayList<>();
        while (matcher.find()) {
            result.add(matcher.group(1));
        }
        return result;
    }

    /**
     * 通过正则表达式替换掉所有匹配到${fieldName}的字符串
     */
    public static String replaceAll(String source, String fieldName, String replacement) {
        Pattern pattern = Pattern.compile("\\$\\{" + fieldName + "}");
        Matcher matcher = pattern.matcher(source);
        String target = source;
        while (matcher.find()) {
            target = matcher.replaceAll(replacement);
            matcher = pattern.matcher(target);
        }
        return target;
    }

    /**
     * 过滤掉字符串中的空格、回车、换行符、制表符
     *
     * @param sourceStr 原始字符串
     * @return 返回格式化后的字符串
     */
    public static String replaceBlank(String sourceStr) {
        String targetStr = "";
        if (sourceStr != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(sourceStr);
            targetStr = m.replaceAll("");
        }
        return targetStr;
    }

    /**
     * 字符串驼峰转下划线格式
     *
     * @param param 需要转换的字符串
     * @return 转换好的字符串
     */
    public static String camelToUnderline(String param) {
        if (StringUtils.isBlank(param)) {
            return StringUtils.EMPTY;
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c) && i > 0) {
                sb.append('_');
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    /**
     * 字符串下划线转驼峰格式
     *
     * @param param 需要转换的字符串
     * @return 转换好的字符串
     */
    public static String underlineToCamel(String param) {
        if (StringUtils.isBlank(param)) {
            return StringUtils.EMPTY;
        }
        String temp = param.toLowerCase();
        int len = temp.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = temp.charAt(i);
            if (c == '_') {
                if (++i < len) {
                    sb.append(Character.toUpperCase(temp.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 首字母转换小写
     *
     * @param param 需要转换的字符串
     * @return 转换好的字符串
     */
    public static String firstToLowerCase(String param) {
        if (StringUtils.isBlank(param)) {
            return StringUtils.EMPTY;
        }
        return param.substring(0, 1).toLowerCase() + param.substring(1);
    }

    /**
     * 判断字符串是否为null或""
     */
    public static boolean isNotEmpty(String value) {
        if (null == value) {
            return false;
        }
        //替换掉转码后的unicode控制字符(这些看不到的空字符无法使用trim移除,每个控制字符的length是1)
        //参考 https://blog.csdn.net/liquantong/article/details/85318595
        value = value.replaceAll("\\u202E", ""); // 开始从右到左的文字
        value = value.replaceAll("\\u202D", ""); // 开始从左到右的文字
        value = value.replaceAll("\\u202C", ""); // 结束上一次定义
        return !("".equals(value.trim()) || "null".equalsIgnoreCase(value.trim()));
    }

    /**
     * 获取随机字符串
     */
    public static String getRandomString(final int length) {
//CHECKSTYLE:OFF
        SecureRandom secRandom = new SecureRandom();
        byte[] result = new byte[Math.max(length, 8)];
        secRandom.nextBytes(result);
        return Hex.encodeHexString(result);
//CHECKSTYLE:ON
    }

}
